﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using GameSchoolApplication.Models; 
using GameSchoolApplication.Repositories;
using GameSchoolApplication.Classes;
using GameSchoolApplication.Models.ViewModels;

namespace GameSchoolApplication.Controllers
{
    /// <summary>
    /// This controller handles all actions related to user accounts. 
    /// 
    /// Author: Krilli
    /// Date: 2.5 13:00
    /// </summary>
    public class AccountController : Controller
    {
        #region createUser
        /// <summary>
        /// Returns the create user view. 
        /// Precondition: A user open the create user page
        /// Postcondition: The create user view is returned to the user. 
        /// Author: Krilli
        /// Date: 2.5 14:00
        /// </summary>
        /// <returns>The page to create a new user</returns>
        public ActionResult createUser()
        {
            return View("CreateUserAccount");
        }

        /// <summary>
        /// Accepts data from the administrator and adds a new user to the database.
        /// Precondition: The administrator submits new user information
        /// Postcondition: The new user is added to the database. 
        /// Author: Krilli
        /// Date: 2.5 15:40
        /// Tested and works beautifully at 3.5 13:45
        /// </summary>
        /// <param name="model">The new user information submitted by the administrator</param>
        /// <returns>A page detailing if the user was created successfully</returns>
        [HttpPost]
        public ActionResult createUser(UserAccount model)
        {
            AccountRepository rep = new AccountRepository();
            //UserAccount newUser = new UserAccount(model.userName, model.password, model.name, model.email, model.isAdmin);
            //If the user was succesfully added to the database: 
            model.lastLogOn = DateTime.Now;
            if (rep.addAccount(model))
            {
                rep.save();
                return View("CreateUserSuccess");
            }
            else
            {
                return View("CreateUserFailure"); 
            }
        }
        #endregion

        #region editUser
        /// <summary>
        /// Returns the edit user view for a specific user. 
        /// Precondition: The administrator submits the user ID to be edited.
        /// Postcondition: The edit user view for that user is returned
        /// Author: Krilli
        /// Date: 2.5 16:10
        /// </summary>
        /// <param name="userID">The ID of the user to be edited</param>
        /// <returns></returns>
        [HttpGet]
        public ActionResult editUser()
        {
            //Initialize repository
            AccountRepository rep = new AccountRepository(); 
            IQueryable<UserAccount> accounts = rep.getAllAccounts();
            return View("UserOverview", accounts); 
        }

        /// <summary>
        /// Returns the edit user page for a specific user 
        /// </summary>
        /// <param name="userID"></param>
        /// <returns></returns>
        [HttpGet]
        public ActionResult editUserPage(string userID)
        {
            //Initialize repository, create the user
            AccountRepository rep = new AccountRepository();
            UserAccount user = new UserAccount(); 
            //get the user in question
            user = rep.getAccountByID(userID);
            //Return the view with the user as model. 
            return View(user); 
        }

        /// <summary>
        /// Submits the edited user information to the database. 
        /// Precondition: The administrator has received the edit user page for that specific user.
        /// Postcondition: The edited user information has been submitted to the database. The user receives a success notification of some description.
        /// Author: Krilli
        /// Date: 2.5 16:40
        /// </summary>
        /// <param name="model">The usermodel for the edted user</param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult editUserPage(UserAccount model)
        {
            //Create Repository instance
            AccountRepository rep = new AccountRepository();
            //Create the account object to be added to the DB
            //UserAccount newUser = new UserAccount(model.ID, model.userName, model.password, model.name, model.email, model.isAdmin);
            //Add the account to the database
            bool worked = rep.editAccount(model);
            if (worked)
            {
                return RedirectToAction("editUser", "Account");
            }
            else
            {
                return View("logonFailed"); 
            }
            //Done! Return view.
            //This might have to be modified, I'm not entirely sure how this view thing works. 
            
        }

        #endregion

        #region logOn
        /// <summary>
        /// Returns the LogOn view to the user. 
        /// Precondition: The user opens the logon page. 
        /// Postcondition: If the user does not have a logon cookie, the user has received the logon page. 
        ///                If the user does have a logon cookie, the user is redirected back to the home page. 
        /// Author: Krilli
        /// Date: 2.5 17:00
        /// </summary>
        /// <returns>The logon view</returns>

        public ActionResult logOn()
        {
            if (Request.Cookies["userInfo"] == null)
            {
               return View("LogOn");
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }

        /// <summary>
        /// Submits the user's logon information and verifies that they match a entry in the database. 
        /// Forwards the user to the index page if user information checks out. 
        /// Precondition: The user has opened the logon page. 
        /// Postcondition: The user's login information has been submitted and verified.
        ///                 If the user information was verified:
        ///                   User is forwarded to the index page.
        ///                   User has a login cookie added to his browser with his userID. 
        ///                 If the user information was not verified:
        ///                   User receives a error message and is asked to try again. 
        /// Author: Krilli
        /// Date: 3.5 10:30
        /// </summary>
        /// <param name="?"></param>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult logOn(LogOnModel model, string returnUrl)
        {
            //Initialize the repository
                AccountRepository rep = new AccountRepository();
                //Try to find the user in question
                try
                {
                    UserAccount user = rep.getAccountByName(model.UserName);
                    //Password check
                    if (user.passW == model.Password)
                    {
                        //Create login cookie.
                        HttpCookie loginCookie = new HttpCookie("userInfo");
                        loginCookie.Values.Add("name", user.userName);
                        loginCookie.Values.Add("userID", user.userID);
                        if (user.isAdmin == true)
                        {
                            loginCookie.Values.Add("isAdmin", "1");
                        }
                        else
                        {
                            loginCookie.Values.Add("isAdmin", "0");
                        }
                        Response.Cookies.Add(loginCookie);
                        /*
                        loginCookie.Value = user.userID.ToString();
                        loginCookie.Expires = DateTime.Now.AddDays(7);
                         * */
                        //Redirect browser to home page. 
                        //NOTE: Might have to change parameters here, not sure what final names for the homecontroller and it's view will be. 
                        return RedirectToAction("Index", "Home");
                    }
                    else
                    {
                        ModelState.AddModelError("", "Innskráning mistókst. Vinsamlegast reynið aftur.");  
                    }
                }
                catch
                {
                    //If getAccountByName does not find the account and throws a error, return to the loginpage.
                    //TODO: Give the user a error somehow. 
                    return View();
                }
                return View(); 
        }
        

        /// <summary>
        /// Determines if a user is a teacher in a course. 
        /// Precondition: The user exists, the course exists .
        /// Postcondition: A bool value is returned. 
        /// Author: Krill
        /// Date: 11.5
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="courseID"></param>
        /// <returns></returns>
        public bool isTeacherInCourse(string userID, int courseID)
        {
            AccountRepository rep = new AccountRepository();
            bool retVal = rep.isTeacherInCourse(userID, courseID);
            return retVal; 
        }

        public string getUserIDFromCookie()
        {
            string userID = Request.Cookies["userInfo"].Values["userID"];
            return userID; 
        }

        #endregion

        #region lostPassword
        /// <summary>
        /// Returns the lost password window to the user. 
        /// Precondition: The user has clicked the lost password button.
        /// Postcondition: The lost password window has been returned to the user.
        /// Author: 
        /// Date:
        /// </summary>
        /// <returns></returns>
        public ActionResult lostPassword()
        {
            
            return View();
        }

        /// <summary>
        /// Submits the user's email address, if it is found in the database, send user's password and username in email to him. 
        /// Precondition: The user is on the lost password page.
        /// Postcondition: The user has submitted email information to the server. 
        ///                 If the email matches that of any account: 
        ///                     Send email to that email with the account's username and password
        ///                 If the email does not match that of any account: 
        ///                     Send user error message, ask him to try again. 
        /// Author: 
        /// Date:
        /// </summary>
        /// <param name="emailAddress">The email address submitted by the user. </param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult lostPassword(lostPasswordRequest data)
        {
            //Initialize the repository, the mailer, and the user
            AccountRepository rep = new AccountRepository();
            UserAccount user = rep.getAccountByID(data.userID);
            if (user == null)
                ModelState.AddModelError("", "That SSN does not exist in our database");
            else if (user.email != data.eMail)
                ModelState.AddModelError("", "Incorrect email address");
            //Try to fetch the user via email address
            else
            {
                try
                {
                    Mailer mailer = new Mailer();
                    mailer.sendLostPasswordMail(user);
                }
                //If error is thrown, return user to the same page. 
                catch
                {
                    ModelState.AddModelError("", "");
                    return View();
                }
            }

            return View();
        }
        #endregion

        #region Other
        /// <summary>
        /// Returns the admin view model to the user. 
        /// Precondition: User clicks the administrator link
        /// Postcondition: User has received the admin view
        /// Author: Krilli
        /// Date: 3.5. 13:00
        /// </summary>
        /// <returns>The admin view</returns>
        public ActionResult Admin()
        {
            return View();
        }

        /// <summary>
        /// Returns listbox overview with users. 
        /// Precondition: User clicks the Useroverview link
        /// Postcondition: User has UserOverview page
        /// Author: Hlynur
        /// Date: 3.5. 14:45
        /// </summary>
        /// <returns></returns>
        public ActionResult UserOverview()
        {
            AccountRepository rep = new AccountRepository();
            return View("UserOverview", rep.getAllAccounts().AsEnumerable()); 
        }
        /*
        public ActionResult getUserList(string searchParam)
        {
            AccountRepository rep = new AccountRepository();

            return View();
        }
        */
        /// <summary>
        /// Logs the user out of the system. 
        /// Precondition: The user is logged in and clicks the logoff link.
        /// Postcondition: User has been logged out of the system and his login cookie has been deleted. He is then redirected to the login page.  
        /// Author: Krilli
        /// Date: 4.5 09:30
        /// </summary>
        /// <param name="userID">The ID of the user being logged off</param>
        /// <returns>Returns the login view</returns>
        public ActionResult logOff()
        {
            //If the user has no cookie
            if (Request.Cookies["userInfo"] == null)
            {
                //Return the logon view. 
                return RedirectToAction("Index", "Home"); 
            }
            else
            {
                //Delete the logon cookie
                Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(-1);
                //Return the login view. 
                return RedirectToAction("Index", "Home");
            }
        }


        public ActionResult getsbux(string userID)
        {
            //Initialize the repository
            AccountRepository rep = new AccountRepository();
            //Fetch sbux
            int? sbux = rep.getAccountByID(userID).sbux;
            int correctSbux = (sbux.HasValue ? sbux.Value : 0);
            //Return the level and the view
            return Json(correctSbux,JsonRequestBehavior.AllowGet);
        }

        public ActionResult getPointsAbove(string userID)
        {
            AccountRepository rep = new AccountRepository();

            int? points = rep.getPointsAbove(userID);
            int r = (points.HasValue ? points.Value : 0);

            return Json(r, JsonRequestBehavior.AllowGet);
        }

        public ActionResult getPointsBelow(string userID)
        {
            AccountRepository rep = new AccountRepository();

            int? points = rep.getPointsBelow(userID);
            int r = (points.HasValue ? points.Value : 0);

            return Json(r, JsonRequestBehavior.AllowGet);
        }
       
        #endregion
    }
}